﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Miris.HumanMilkAnalyser.DataModel;
using Miris.HumanMilkAnalyser.Service;
using Miris.HumanMilkAnalyser.Service.Shared;
using Miris.HumanMilkAnalyser.WPF.Model;
using Miris.HumanMilkAnalyser.WPF.Shared;

namespace Miris.HumanMilkAnalyser.WPF.ViewModel
{
    public class AnalysisReportViewModel : AnalysisResultViewModel
    {
        public bool IncludeBreastfeedingSignificance { get; set; }
        public string AttachedDiagnosticMessage { get; set; }

        /// <summary>
        /// Initializes a new instance of the AnalysisReportViewModel class.
        /// </summary>
        public AnalysisReportViewModel(IDataService dataService)
            : base(dataService) { }

        public override void ResetProperties()
        {
            base.ResetProperties();

            SetProperties(ServiceFactory.CreateBasicConfigurationService().Load());
            SetCurrentMilkStageDisplay();
            SetCurrentMilkSampleDisplay();
            SetDiagnosticMessages();
            LoadAnalysisResult();
            LoadBreastfeedingSignificance();
        }

        /// <summary>
        /// The <see cref="CompanyName" /> property's name.
        /// </summary>
        public const string CompanyNamePropertyName = "CompanyName";

        private string _companyName = string.Empty;

        /// <summary>
        /// Sets and gets the CompanyName property.
        /// Changes to that property's value raise the PropertyChanged event. 
        /// </summary>
        public string CompanyName
        {
            get
            {
                return _companyName;
            }

            set
            {
                if (_companyName == value)
                {
                    return;
                }

                RaisePropertyChanging(CompanyNamePropertyName);
                _companyName = value;
                RaisePropertyChanged(CompanyNamePropertyName);
            }
        }

        /// <summary>
        /// The <see cref="CompanyLogoFileFullName" /> property's name.
        /// </summary>
        public const string CompanyLogoFileFullNamePropertyName = "CompanyLogoFileFullName";

        private string _companyLogoFileFullName = string.Empty;

        /// <summary>
        /// Sets and gets the CompanyLogoFileFullName property.
        /// Changes to that property's value raise the PropertyChanged event. 
        /// </summary>
        public string CompanyLogoFileFullName
        {
            get
            {
                return _companyLogoFileFullName;
            }

            set
            {
                if (_companyLogoFileFullName == value)
                {
                    return;
                }

                RaisePropertyChanging(CompanyLogoFileFullNamePropertyName);
                _companyLogoFileFullName = value;
                RaisePropertyChanged(CompanyLogoFileFullNamePropertyName);
            }
        }

        /// <summary>
        /// The <see cref="CompanyAddress" /> property's name.
        /// </summary>
        public const string CompanyAddressPropertyName = "CompanyAddress";

        private string _companyAddress = string.Empty;

        /// <summary>
        /// Sets and gets the CompanyAddress property.
        /// Changes to that property's value raise the PropertyChanged event. 
        /// </summary>
        public string CompanyAddress
        {
            get
            {
                return _companyAddress;
            }

            set
            {
                if (_companyAddress == value)
                {
                    return;
                }

                RaisePropertyChanging(CompanyAddressPropertyName);
                _companyAddress = value;
                RaisePropertyChanged(CompanyAddressPropertyName);
            }
        }

        /// <summary>
        /// The <see cref="CompanyPhoneNumber" /> property's name.
        /// </summary>
        public const string CompanyPhoneNumberPropertyName = "CompanyPhoneNumber";

        private string _companyPhoneNumber = string.Empty;

        /// <summary>
        /// Sets and gets the CompanyPhoneNumber property.
        /// Changes to that property's value raise the PropertyChanged event. 
        /// </summary>
        public string CompanyPhoneNumber
        {
            get
            {
                return _companyPhoneNumber;
            }

            set
            {
                if (_companyPhoneNumber == value)
                {
                    return;
                }

                RaisePropertyChanging(CompanyPhoneNumberPropertyName);
                _companyPhoneNumber = value;
                RaisePropertyChanged(CompanyPhoneNumberPropertyName);
            }
        }

        /// <summary>
        /// The <see cref="TestReportTitle" /> property's name.
        /// </summary>
        public const string TestReportTitlePropertyName = "TestReportTitle";

        private string _testReportTitle = string.Empty;

        /// <summary>
        /// Sets and gets the TestReportTitle property.
        /// Changes to that property's value raise the PropertyChanged event. 
        /// </summary>
        public string TestReportTitle
        {
            get
            {
                return _testReportTitle;
            }

            set
            {
                if (_testReportTitle == value)
                {
                    return;
                }

                RaisePropertyChanging(TestReportTitlePropertyName);
                _testReportTitle = value;
                RaisePropertyChanged(TestReportTitlePropertyName);
            }
        }

        /// <summary>
        /// The <see cref="DepartmentName" /> property's name.
        /// </summary>
        public const string DepartmentNamePropertyName = "DepartmentName";

        private string _departmentName = string.Empty;

        /// <summary>
        /// Sets and gets the DepartmentName property.
        /// Changes to that property's value raise the PropertyChanged event. 
        /// </summary>
        public string DepartmentName
        {
            get
            {
                return _departmentName;
            }

            set
            {
                if (_departmentName == value)
                {
                    return;
                }

                RaisePropertyChanging(DepartmentNamePropertyName);
                _departmentName = value;
                RaisePropertyChanged(DepartmentNamePropertyName);
            }
        }

        /// <summary>
        /// The <see cref="DiagnosticMessages" /> property's name.
        /// </summary>
        public const string DiagnosticMessagesPropertyName = "DiagnosticMessages";

        private string _diagnosticMessages = string.Empty;

        /// <summary>
        /// Sets and gets the DiagnosticMessages property.
        /// Changes to that property's value raise the PropertyChanged event. 
        /// </summary>
        public string DiagnosticMessages
        {
            get
            {
                return _diagnosticMessages;
            }

            set
            {
                if (_diagnosticMessages == value)
                {
                    return;
                }

                RaisePropertyChanging(DiagnosticMessagesPropertyName);
                _diagnosticMessages = value;
                RaisePropertyChanged(DiagnosticMessagesPropertyName);
            }
        }

        /// <summary>
        /// The <see cref="CurrentMilkSampleDisplay" /> property's name.
        /// </summary>
        public const string CurrentMilkSampleDisplayPropertyName = "CurrentMilkSampleDisplay";

        private string _currentMilkSampleDisplay = string.Empty;

        /// <summary>
        /// Sets and gets the CurrentMilkSampleDisplay property.
        /// Changes to that property's value raise the PropertyChanged event. 
        /// </summary>
        public string CurrentMilkSampleDisplay
        {
            get
            {
                return _currentMilkSampleDisplay;
            }

            set
            {
                if (_currentMilkSampleDisplay == value)
                {
                    return;
                }

                RaisePropertyChanging(CurrentMilkSampleDisplayPropertyName);
                _currentMilkSampleDisplay = value;
                RaisePropertyChanged(CurrentMilkSampleDisplayPropertyName);
            }
        }

        /// <summary>
        /// The <see cref="CurrentMilkStageDisplay" /> property's name.
        /// </summary>
        public const string CurrentMilkStageDisplayPropertyName = "CurrentMilkStageDisplay";

        private string _currentMilkStageDisplay = string.Empty;

        /// <summary>
        /// Sets and gets the CurrentMilkStageDisplay property.
        /// Changes to that property's value raise the PropertyChanged event. 
        /// </summary>
        public string CurrentMilkStageDisplay
        {
            get
            {
                return _currentMilkStageDisplay;
            }

            set
            {
                if (_currentMilkStageDisplay == value)
                {
                    return;
                }

                RaisePropertyChanging(CurrentMilkStageDisplayPropertyName);
                _currentMilkStageDisplay = value;
                RaisePropertyChanged(CurrentMilkStageDisplayPropertyName);
            }
        }

        /// <summary>
        /// The <see cref="AnalysisResultList" /> property's name.
        /// </summary>
        public const string AnalysisResultListPropertyName = "AnalysisResultList";

        private ObservableCollection<AllTestItemsViewModel> _analysisResultList = new ObservableCollection<AllTestItemsViewModel>();

        /// <summary>
        /// Sets and gets the AnalysisResultList property.
        /// Changes to that property's value raise the PropertyChanged event. 
        /// </summary>
        public ObservableCollection<AllTestItemsViewModel> AnalysisResultList
        {
            get
            {
                return _analysisResultList;
            }

            set
            {
                if (_analysisResultList == value)
                {
                    return;
                }

                RaisePropertyChanging(AnalysisResultListPropertyName);
                _analysisResultList = value;
                RaisePropertyChanged(AnalysisResultListPropertyName);
            }
        }

        /// <summary>
        /// The <see cref="DignosticMessageList" /> property's name.
        /// </summary>
        public const string DignosticMessageListPropertyName = "DignosticMessageList";

        private ObservableCollection<DiagnosticMessageReference> _dignosticMessageList = new ObservableCollection<DiagnosticMessageReference>();

        /// <summary>
        /// Sets and gets the DignosticMessageList property.
        /// Changes to that property's value raise the PropertyChanged event. 
        /// </summary>
        public ObservableCollection<DiagnosticMessageReference> DignosticMessageList
        {
            get
            {
                return _dignosticMessageList;
            }

            set
            {
                if (_dignosticMessageList == value)
                {
                    return;
                }

                RaisePropertyChanging(DignosticMessageListPropertyName);
                _dignosticMessageList = value;
                RaisePropertyChanged(DignosticMessageListPropertyName);
            }
        }

        /// <summary>
        /// The <see cref="CurrentBreastfeedingSignificance" /> property's name.
        /// </summary>
        public const string CurrentBreastfeedingSignificancePropertyName = "CurrentBreastfeedingSignificance";

        private BreastfeedingSignificance _currentBreastfeedingSignificance = null;

        /// <summary>
        /// Sets and gets the CurrentBreastfeedingSignificance property.
        /// Changes to that property's value raise the PropertyChanged event. 
        /// </summary>
        public BreastfeedingSignificance CurrentBreastfeedingSignificance
        {
            get
            {
                return _currentBreastfeedingSignificance;
            }

            set
            {
                if (_currentBreastfeedingSignificance == value)
                {
                    return;
                }

                RaisePropertyChanging(CurrentBreastfeedingSignificancePropertyName);
                _currentBreastfeedingSignificance = value;
                RaisePropertyChanged(CurrentBreastfeedingSignificancePropertyName);
            }
        }

        /// <summary>
        /// Set CurrentMilkStageDisplay property based on CurrentAnalysisResult.
        /// </summary>
        private void SetCurrentMilkStageDisplay()
        {
            switch (CurrentAnalysisResult.SampleStageType)
            {
                case (byte)MilkStage.Unmature:
                    CurrentMilkStageDisplay = "初乳";
                    break;
                case (byte)MilkStage.Transitional:
                    CurrentMilkStageDisplay = "过渡乳";
                    break;
                case (byte)MilkStage.Mature:
                    CurrentMilkStageDisplay = "成熟乳";
                    break;
            }
        }

        /// <summary>
        /// Set CurrentMilkSampleDisplay property based on CurrentAnalysisResult.
        /// </summary>
        private void SetCurrentMilkSampleDisplay()
        {
            switch (CurrentAnalysisResult.SampleType)
            {
                case (byte)MilkSample.Front:
                    CurrentMilkSampleDisplay = "前段";
                    break;
                case (byte)MilkSample.Middle:
                    CurrentMilkSampleDisplay = "中段";
                    break;
                case (byte)MilkSample.End:
                    CurrentMilkSampleDisplay = "后段";
                    break;
                case (byte)MilkSample.Full:
                    CurrentMilkSampleDisplay = "全乳";
                    break;
            }
        }

        /// <summary>
        /// Load TOP 6 analysis result data based on current patient number.
        /// </summary>
        private void LoadAnalysisResult()
        {
            var analysisResults = ServiceFactory.CreateAnalysisResultService().GetAllRelatedTestResultsByPatientNumber(Number, 5);
            ViewModelHelper.FillAllTestItemsViewModelCollection(analysisResults, AnalysisResultList);
        }

        private void LoadBreastfeedingSignificance()
        {
            CurrentBreastfeedingSignificance = ServiceFactory.CreateBreastfeedingSignificanceService().GetAll().FirstOrDefault();
        }

        /// <summary>
        /// Set the property DiagnosticMessages.
        /// </summary>
        private void SetDiagnosticMessages()
        {
            DiagnosticMessages = string.Empty;

            foreach (var diagnosticMessage in DignosticMessageList)
            {
                DiagnosticMessages += diagnosticMessage.MessageContent + ";";
            }

            DiagnosticMessages += AttachedDiagnosticMessage;
        }

        /// <summary>
        /// Set current all properties based on provided instance of BasicConfiguration.
        /// </summary>
        /// <param name="entity">The instance of BasicConfiguration that contains all data.</param>
        private void SetProperties(BasicConfiguration entity)
        {
            CompanyName = entity.CompanyName;
            CompanyLogoFileFullName = entity.CompanyLogoFileFullName;
            CompanyAddress = entity.CompanyAddress;
            CompanyPhoneNumber = entity.CompanyPhoneNumber;
            TestReportTitle = entity.TestReportTitle;
            DepartmentName = entity.DepartmentName;
        }
    }
}
